
#include "SymbolTable.h"
#include "global.h"
#include <stdio.h>
using namespace std;
static int lastpost;
ScopeLevelTable::ScopeLevelTable(){
	for(int i=0;i<16; i++){
		for(int j=0;j<2;j++){
			table[i][j] = 0;
		}
	}
}
void ScopeLevelTable::enterscope(int level, int s, int e){
	table[level][0] = s;
	table[level][1] = e;
}
int* ScopeLevelTable::leavescope(int level){
	int* range = new int[2];
	range[0] = table[level][0];
	range[1] = table[level][1];
	return range;
}
int* ScopeLevelTable::getRange(int level){
	int* range = new int[2];
	range[0] = table[level][0];
	range[1] = table[0][1];
	return range;
}
int* ScopeLevelTable::getLocalRange(int level){
	int* range = new int[2];
	range[0] = table[level][0];
	range[1] = table[level][1];
	return range;
}

symbolTableObj::symbolTableObj(){

}

SymbolTable::SymbolTable():stackSP(-1),currentLevel(0),startItem(0),endItem(0),isFirstItemAdded(0){
	 for(int i=0; i< MAX_SYMBOL_TABLE_OBJECT;i++){
		 symboltable[i] = emptySymbolTableObj;		 
		 //printf("%x\n",&symboltable[i]);
		 //cout <<&symboltable[i] <<endl;
	 }
}
SymbolTable::~SymbolTable(){
}
const int SymbolTable::getObjectPosition(symbolTableObj& obj) const{
	return obj.address;
}
symbolTableObj* SymbolTable::lookup_symbol_entry(char name[]){
	bool found = false;
	if(stackSP ==-1) return 0;
	//symbolTableObj* ptr = &symboltable[0];
	
	lastpost = stackSP;
	int* range = leveltable.getLocalRange(currentLevel);
	symbolTableObj* ptr = &symboltable[stackSP]; // SEARCH FROM THE TOP OF THE STACK

	

	while(!found && ptr>=&symboltable[0]){
		if (compare(ptr->name, name)){
		
			found = true;
			
			//cout << "It is : " << ptr << endl;
			return ptr;
		}
		else{
			lastpost--;
			ptr--;
		}
	}
	return 0;

}
void SymbolTable::enterScope(){
	isFirstItemAdded= 0;
	if (startItem==(endItem+1)) { 
		//indicate that there is no local variable in the previous level
		leveltable.enterscope(currentLevel,startItem,-1);

	}
	else{

		leveltable.enterscope(currentLevel,startItem,endItem);
	}
	
	if(startItem==(endItem+1)) {
		currentLevel++;
	}
	else{
	startItem++;
	//endItem = startItem;
	endItem = stackSP;
	currentLevel++;
	}
}
void SymbolTable::leaveScope(){
	
	int* range = leveltable.leavescope(currentLevel-1);
	currentLevel--;
	

	if(endItem!=-1){

		for(int i=stackSP; i>=endItem; i--){
			
			symbolTableObj* r = remove_symbol_entry();
		//delete r;
		}
	}
	startItem = (*range);
	endItem = (*(range+1));
	isFirstItemAdded = (endItem!=-1);	
	
}
// push
int SymbolTable::insert_symbol_entry(symbolTableObj& symbol){
	if(stackSP>=MAX_SYMBOL_TABLE_OBJECT){
		return -1;
	}
	symbolTableObj* obj;
	int* range = leveltable.getLocalRange(currentLevel);

		
	obj = lookup_symbol_entry(symbol.name);
	if(!obj){

		/*int offset = stackSP-TOP_STACK;
		symboltable[offset] = symbol;
		stackSP++;*/
		stackSP++;
		startItem = stackSP;
		symbol.address= stackSP;
		symboltable[stackSP] = symbol;
		if(!isFirstItemAdded){
			endItem= startItem;
			isFirstItemAdded = 1;
		}
		return SUCESS;
	}
	else{
		symbolTableObj* s ;
		symbolTableObj* e;
		if(!isFirstItemAdded){
			printf("no local variable in the level.\n");
			printf("%d\n",stackSP);
			printf("%d\n",endItem);
			stackSP++;
			startItem = stackSP;
			symboltable[stackSP] = symbol;
			if(!isFirstItemAdded) {
				isFirstItemAdded = 1;
				endItem= startItem;
			}
			return SUCESS;
		}
		else{
			s = &symboltable[endItem];
			e = &symboltable[stackSP];		
		

		printf("FROM: %s\n",s);
		printf("%s\n",obj);
		printf("TO: %s\n",e);
		
		

		if(obj <=e && obj >=s) {
		//if(obj <= &symboltable[*(range+1)]){
		
			printf("same level\n");
		}
		else{
			printf ("different level\n");
			stackSP++;
			startItem = stackSP;
			symboltable[stackSP] = symbol;
			if(!isFirstItemAdded) endItem++;
			return SUCESS;
		}
	}
		return SYMBOL_EXISTED;
	}
}
//pop
symbolTableObj* SymbolTable::remove_symbol_entry(){
	if(stackSP< 0){
		return 0;
	}
	symboltable[stackSP] = emptySymbolTableObj;
	symbolTableObj* last = &symboltable[stackSP];	
	stackSP--;
	return last;
}
symbolTableObj* SymbolTable::top(){
	return &symboltable[stackSP];
}
bool SymbolTable::isEmpty() const {
	return ( stackSP < 0 ) ? true : false;
}
int SymbolTable::size() const{
	//return (stackSP - BASE_STACK) / sizeof(symbolTableObj);
	return stackSP;
}
symbolTableObj* SymbolTable::getSymbolObj(int index){
	return &symboltable[index];
}



